package prueba.prueba.helpers;
import java.util.HashMap;
import java.util.LinkedList;

import prueba.prueba.PruebaActivity;
import prueba.prueba.TypeWords;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
 
public class WordsISOHelper extends SQLiteOpenHelper {
 
    //Sentencia SQL para crear la tabla de Usuarios
	
	
	//id	es	en	fr	de	ru	ar	ch	jp
    String sqlCreate = "CREATE TABLE words_iso (id INTEGER,md5 TEXT,type INTEGER,es TEXT,en TEXT,fr TEXT,de TEXT,ru TEXT,ar TEXT,ch TEXT,jp TEXT)";
    String sqlCreatepractices = "CREATE TABLE practices (md5 TEXT,type_practice INTEGER,iso TEXT,num_hits INTEGER,num_practices INTEGER)";
    
    
    public WordsISOHelper(Context contexto, String nombre,CursorFactory factory, int version) {
        super(contexto, nombre, factory, version);
    }
 
    @Override
    public void onCreate(SQLiteDatabase db) {
        //Se ejecuta la sentencia SQL de creación de la tabla
        db.execSQL(sqlCreate);
        db.execSQL(sqlCreatepractices);
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase db, int versionAnterior, int versionNueva) {
        //NOTA: Por simplicidad del ejemplo aquí utilizamos directamente la opción de
        //      eliminar la tabla anterior y crearla de nuevo vacía con el nuevo formato.
        //      Sin embargo lo normal será que haya que migrar datos de la tabla antigua
        //      a la nueva, por lo que este método debería ser más elaborado.
 
        //Se elimina la versión anterior de la tabla
        db.execSQL("DROP TABLE IF EXISTS words_iso");
        db.execSQL("DROP TABLE IF EXISTS practices");
 
        //Se crea la nueva versión de la tabla
        db.execSQL(sqlCreate);
    }
    
    
    
    // Comprobar si existe y actualizar, etc.
    public void create(int id,int type_word,String es,String en,String fr,String de,String ru,String ch,String ar,String jp,String md5){
    	 //Insertamos los datos en la tabla Usuarios
    		//Toast.makeText(null,"inserta un registro",Toast.LENGTH_SHORT).show();
    	try{
    		getWritableDatabase().execSQL("INSERT INTO words_iso (id,type,es,en,fr,de,ru,ar,ch,jp,md5) " + "VALUES (" + id + "," + type_word +",'" + es +"','" + en +"','" + fr +"','" + de +"','" + ru +"','" + ch +"','" + ar +"','" + jp +"','" + md5 +"')");
    	}
    	catch(Exception ex){
    		String log = ex.getMessage() + ex.getCause();
    		Log.i("SQL","Peta por caracteres utf8" + log);
    	}
    }
    
    public void delete(int id){
    	try{
    		getWritableDatabase().delete("words_iso","id=?",new String[]{id + ""});
    		//getWritableDatabase().execSQL("DELETE words WHERE id = " + id);
    	}
    	catch(Exception ex){
    		Log.e("SQL","Peta al borrar un registro");
    	}
    }
    
    public void deleteAll(){
    	try{
    		getWritableDatabase().delete("words_iso","",new String[]{});
    		//getWritableDatabase().execSQL("DELETE words WHERE id = " + id);
    	}
    	catch(Exception ex){
    		Log.e("SQL","Peta al borrar un registro");
    	}
    }
    
    
    // Especializarlo por iso. 
    public void clearHistory(){
    	try{
    		getWritableDatabase().delete("practices","",new String[]{});
    		//getWritableDatabase().execSQL("DELETE words WHERE id = " + id);
    	}
    	catch(Exception ex){
    		Log.e("SQL","Peta al borrar un registro");
    	}
    }
    
    
    public void setPractice(String md5,String iso,int num_practices,int num_hits,int type_practice){
    	
    	try{
    		
   //   String sqlCreatepractices = "CREATE TABLE practices (md5 TEXT,type_practice INTEGER,iso TEXT,num_hits INTEGER,num_practices INTEGER)";
    		   
    		String condition = "md5='" + md5 +"' AND type_practice=" + type_practice + " AND iso='"+iso+"'";
    		getWritableDatabase().delete("practices",condition,new String[]{});
    		//getWritableDatabase().execSQL("DELETE words WHERE id = " + id);
    	}
    	catch(Exception ex){
    		String log = ex.getMessage() + ex.getCause();
    		Log.e("SQL","Peta al borrar un registro" + log);
    	}
    	
    	
    	try{
    		getWritableDatabase().execSQL("INSERT INTO practices (md5,type_practice,iso,num_hits,num_practices) " + "VALUES ('" + md5 + "'," + type_practice +",'" + iso +"'," + num_hits +"," + num_practices +")");
    	}
    	catch(Exception ex){
    		String log = ex.getMessage() + ex.getCause();
    		Log.i("SQL","Peta por caracteres utf8" + log);
    	}
    	
    	
    }
      
    private LinkedList<Integer> select_id_words(int id_type,String language,int type_practice){
 
    	/* Instrucciones.
    	 * 
    	 * Seleccionar todos los md5 de words, que no esten en la tabla de practices, con las condiciones tal.
    	 * 
    	 * 
    	 * 
    	 * 
    	 * 
    	 * 
    	 */
    	
    	LinkedList<String> list_md5 = new LinkedList<String>();
		
    	Cursor c = null;
    	
    	String[] args = new String[]{};
    	String querymd5 = "SELECT md5 FROM practices WHERE iso ='" + language + "' AND type_practice="+type_practice+" ORDER by num_practices";//length("+language+") > 0 AND type = " + id_type;

    	Log.i("query",querymd5);
 		try {
			c = getWritableDatabase().rawQuery(querymd5,args);
			
			//Nos aseguramos de que existe al menos un registro
			if (c.moveToFirst()) {
			     do {
			    	list_md5.add(c.getString(0));
			  
			     } while(c.moveToNext());
			}
		} catch (Exception e1) {
			String error = e1.getMessage() + e1.getCause();
			Log.i("",error);
		}

    	// #### Condiciones para seleccionar un id ####
    	
    	// Que la iso no este vacia.
    	// Que coincida el tipo de palabra.
    	// Extra: Que cumpla las reglas del historial.
    	
    	LinkedList<Integer> list = new LinkedList<Integer>();
    		
    	
    	args = new String[]{};
    	String md5s = "'" + implode_string(list_md5,"','") + "'";
    	String query = "SELECT id FROM words_iso WHERE length("+language+") > 0 AND type = " + id_type+" AND md5 NOT IN (" +md5s+ ")";
    	
    	Log.i("query",query);
 		try {
			c = getWritableDatabase().rawQuery(query,args);
			
			//Nos aseguramos de que existe al menos un registro
			if (c.moveToFirst()) {
			     do {
			    	list.add(c.getInt(0));
			  
			     } while(c.moveToNext());
			}
		} catch (Exception e) {
			String text = e.getCause() + e.getMessage();
			Log.e("",text);
		}
 		
 		// Si la lista no es lo suficientemente grande, buscamos en los ids del historial.
 		
 		
 		if (list.size() < PruebaActivity.num_practices){
 			LinkedList<Integer> list_md5_id = select_words_md5(list_md5);
 			
 			for (int i = 0; i < Math.min(list_md5_id.size(),PruebaActivity.num_practices - list.size());i++){
 				list.add(list_md5_id.get(0));
 			}
 		}

 		return list;    	
    }
    
    
    
    
    
private LinkedList <Integer> select_words_md5(LinkedList<String> list){ // Agregar el tipo de practica.
    	
    	list.add("");
    	LinkedList<Integer> ret = new LinkedList<Integer>();
		
    	Cursor c = null;
    	
    	String[] args = new String[]{};
    	String md5s = "'" + implode_string(list,"','") + "'";
    	String query = "SELECT * FROM words_iso WHERE md5 IN ("+md5s+")";
    	//query = "SELECT * FROM words_iso";
    	
    	Log.i("query",query);
 		c = getWritableDatabase().rawQuery(query,args);
     	
 		//Nos aseguramos de que existe al menos un registro
 		if (c.moveToFirst()) {
 		  
 		     do {	    	 
 		    	 ret.add(c.getInt(0));
 		     } while(c.moveToNext());
 		}
 		
 		return ret; 	
    }

 private LinkedList <WordIso> select_words(LinkedList<Integer> list){ // Agregar el tipo de practica.
    	
    	list.add(0);
    	LinkedList <WordIso> list_word = new LinkedList<WordIso>();
    	
    	Cursor c = null;
    	
    	String[] args = new String[]{};
    	String query = "SELECT * FROM words_iso WHERE id IN ("+WordsISOHelper.implode(list,",")+")";
    	//query = "SELECT * FROM words_iso";
    	
    	Log.i("query",query);
 		c = getWritableDatabase().rawQuery(query,args);
     	
 		//Nos aseguramos de que existe al menos un registro
 		if (c.moveToFirst()) {
 		     //Recorremos el cursor hasta que no haya más registros
 			TypeWords type = null;
 			try{
 				type = TypeWords.values()[c.getInt(1)];
 			}
 			catch(Exception ex){
 				type = TypeWords.sustantivos;
 			}
 			int counter = 0;
 		     do {
 		    	 
 		    	 HashMap<String,String> meanings = new HashMap<String,String>();
 		    	 
 		    	meanings.put("es",c.getString(3));
 		    	meanings.put("en",c.getString(4));
 		    	meanings.put("fr",c.getString(5)); // completar el resto de traducciones.
 		    	
 		    	meanings.put("de",c.getString(6));
		    	meanings.put("ru",c.getString(7));
		    	meanings.put("ar",c.getString(8)); // completar el resto de traducciones.
		    	
		    	meanings.put("ch",c.getString(9));
 		    	meanings.put("jp",c.getString(10));
 		    	
 		    		    	 
 		    	//id INTEGER,type INTEGER,es TEXT,en TEXT,fr TEXT,de TEXT,ru TEXT,ar TEXT,ch TEXT,jp TEXT
 		    	 //id	word	meaning	language	type	num_practices	num_hits	ts
 		    	 list_word.add(new WordIso(c.getInt(0),meanings,type,c.getString(1))); // de momento no es necesario el constructor anterior.
 		    	 counter++;
 		    	 
 		     } while(c.moveToNext() || counter <= PruebaActivity.num_practices);
 		}
 		
 		return list_word;
 	
    }
    
    
    
    
    public LinkedList <WordIso> select_words(int id_type,String language,int type_practice){ // Agregar el tipo de practica.
    	
    	LinkedList<Integer> list = select_id_words(id_type,language,type_practice);
    	return select_words(list);
    }
    
    
    public static String implode_string(LinkedList<String> list, String delim) {
        String out = "";
        for(int i=0; i< list.size(); i++) {
            if(i!=0) { out += delim; }
            out += list.get(i);
        }
        return out;
    }  
    
    public static String implode(LinkedList<Integer> list, String delim) {
        String out = "";
        for(int i=0; i< list.size(); i++) {
            if(i!=0) { out += delim; }
            out += list.get(i);
        }
        return out;
    }  
}